23.07.22
오늘 한 일
- Gloddy 개발
Gloddy 개발 - useFunnel 타입 추론
useFunnel
을 직접 구현하면서 타입 추론이 잘 안되는 문제가 있었다.
const { Funnel, prevStep, nextStep } = useFunnel(['praise', 'mate']);
return (
<Funnel>
<Funnel.Step name="이상한스텝으로적어도에러안뜸">
<PraiseComponent onPrevClick={prevStep} onNextClick={nextStep} />
</Funnel.Step>
<Funnel.Step name="mate">
<MateComponent onPrevClick={prevStep} onNextClick={nextStep} />
</Funnel.Step>
</Funnel>
);
이 부분은 내부적으로 에러를 던져서 막아주긴 했는데, 더 나아가서 리터럴 타입으로 추론이 되도록 하고 싶었다.
토스의 useFunnel은 어떻게 했을까?
토스의 useFunnel
은 as const
로 타입 단언해서 리터럴 타입으로 추론이 가능하게 했다.
타입 단언 안하면 추론 못한다는 것이다. 나는 내부적으로 처리해서 타입 단언을 안해도 되도록 만들고 싶었다.
내 방식
useFunnel
의 파라미터로 넘겨주는 steps
를 readonly 붙여서 리터럴 타입으로 만들었다.
export function useFunnel<Steps extends NonEmptyArray<string>>(
steps: readonly [...Steps],
options?: { initialStep?: Steps[number]; stepQueryKey?: string }
) {
//...
}
이제 useFunnel에서 타입 단언하지 않아도 리터럴 타입으로 추론이 가능하다..!!
readonly Steps
로 하면 다음과 같은 에러메시지가 뜬다.
'readonly' type modifier is only permitted on array and tuple literal types.
readonly는 배열과 튜플 리터럴 타입에만 허용된다고 한다. Steps는 그냥 type이기 때문에 readonly를 붙일 수 없다.
해결법은 두 가지다.
readonly [...Steps]
: 튜플 리터럴 타입으로 변환Readonly<Steps>
: Readonly 타입으로 변환
type Readonly<T> = {
readonly [P in keyof T]: T[P];
};
Readonly
는 제네릭 T의 모든 프로퍼티를 readonly로 변환하는 타입이다.
Gloddy 개발 - react-hook-form 에러 해결
어제 잘 안됐던 문제를 해결했다.
일단 저 에러는 Deepl 번역 크롬 확장 프로그램의 문제였다.. 그냥 지워버리니 해결됐다.
근데 다른 문제가 있었다. textarea에 입력을 하면 focus가 사라진다.
이 문제는 부모 컴포넌트에서 react-hook-form
의 handleSubmit
까지 자식 컴포넌트로 넘겨주면서 발생했다.
// 부모 컴포넌트
export default function FeedbackWrapper() {
const { Funnel, prevStep, nextStep } = useFunnel(['praise', 'mate']);
const { handleSubmit, control } = useFeedbackContext();
const onSubmit = (data: FeedbackRequestType) => {
console.log(data);
};
return (
<Funnel>
<Funnel.Step name="praise">
<PraiseComponent onPrevClick={prevStep} onNextClick={nextStep} />
</Funnel.Step>
<Funnel.Step name="mate">
<MateComponent
onPrevClick={prevStep}
onNextClick={handleSubmit(onSubmit)} // 이 부분
control={control}
/>
</Funnel.Step>
</Funnel>
);
부모에게서 넘겨받은 handleSubmit(onSubmit)
과 내부적으로 사용하는 useFeedbackContext
가 겹쳐져서 렌더링 이슈가 발생한 것 같다.
그래서 자식 컴포넌트 쪽에서 이렇게 처리했다.
// 자식 컴포넌트
export default function MateComponent({ onPrevClick, onNextClick }: MateComponentProps) {
const {
handleSubmit,
formState: { isDirty, isValid },
} = useFeedbackContext();
return (
<main>
<TopNavigationBar
text="최고의 짝꿍"
leftNode={
<Image
src="/assets/arrow_back.svg"
width={8}
height={30}
alt="back"
onClick={onPrevClick}
className="cursor-pointer"
/>
}
/>
<MateCardList userList={DUMMY_USERLIST} />
<Spacing size={100} />
<BottomFixedButton
text="완료"
onClick={handleSubmit(onNextClick!)}
disabled={!isDirty || !isValid}
/>
</main>
);
}
onNextClick
을 handleSubmit
으로 감싸서 넘겨주어서 해결했다.
내일 할 일
- 휴식